local tools = {}

-- 获取人物面前的坐标
function tools:calcCoordFront(inst,dist,angle,player_pos_x,player_pos_z)
    local angle = angle or inst.Transform:GetRotation()
    if player_pos_x and player_pos_z then 
    else 
        player_pos_x,_,player_pos_z = inst.Transform:GetWorldPosition()
    end

    local radian_angle = (angle-90) * math.pi / 180
    return player_pos_x - dist * math.sin(radian_angle), player_pos_z - dist * math.cos(radian_angle)
end
-- 获取默认方向到指定方向的转角
function tools:angleBetweenVectors(x1, z1, x2, z2)
    -- @param :从点(x1,z1)到点(x2,z2)的向量
    local x0,z0 = x1 + 1,z1
    local vec1X,vec1Z = x0 - x1,z0 - z1 -- 默认方向向量
    local vec2X,vec2Z = x2 - x1,z2 - z1 -- 向量AB

    local dotProduct = vec1X * vec2X + vec1Z * vec2Z -- 点乘
    local magA,magB = math.sqrt(vec1X^2+vec1Z^2),math.sqrt(vec2X^2+vec2Z^2) -- 向量模长
    
    local cosTheta = dotProduct / (magA * magB) -- 余弦值
    local theta = math.deg(math.acos(cosTheta)) -- 角度
    if z2-z1>0 then theta = 360-theta end -- 旋转是固定顺时针的,所以要转的角度超过180度时,要...
    return theta
end
-- 获取两点间的距离
function tools:calcDist(x1,z1,x2,z2,do_sqrt)
    -- @param: do_sqrt 是否开平方
    local dist = (x1-x2)^2+(z1-z2)^2
    if do_sqrt then dist = math.sqrt(dist) end
    return dist
end
-- 根据转角获取坐标
function tools:calcRotatedCoords(x1, z1, theta, dist)
    -- @param x1,z1: 线段起点
    -- @param dist: 线段长度
    -- @param theta: 线段与默认方向的夹角(带符号)
    local radian = math.rad(theta)
    local x2 = x1 + dist * math.cos(radian)
    local z2 = z1 - dist * math.sin(radian)
    return x2, z2
end
-- 获取直线上的某个点(在给定的一条直线上找到距离起点 `(x2, z2)` 指定距离 `n` 的点。这条直线由两点 `(x1, z1)` 和 `(x2, z2)` 定义)
function tools:findPointOnLine(x1, z1, x2, z2, dist, n)
    local dx,dz = x1-x2,z1-z2
    local unitDX,unitDZ = dx/dist,dz/dist
    local newX, newZ = x2+unitDX*n ,z2+unitDZ*n
    return newX, newZ
end
-- 获取圆周上的某个点
function tools:findPointOnCircle(x,z,radius,direction,angle)
    -- @param: direction 1:顺时针 -1:逆时针
    -- @param: angle 角度()
    -- @param: radius 半径
    angle = angle*direction
    local des_x = x + math.cos(math.rad(angle))*radius
    local des_z = z + math.sin(math.rad(angle))*radius
    
    return des_x, des_z
end

-- 锥形区域伤害计算(如果张角比较大用下面的;如果张角太小,就当成激光了,分成一个个圈来遍历)
-- 1/2 计算圆锥的外切圆
function tools:coneExcircle(maxRange, centerX, centerZ, pointOnAxis_X, pointOnAxis_Z,angle)
    -- @param maxRange:圆锥的最大长度
    -- @param centerX,centerZ:圆锥的圆心X,Z坐标
    -- @param pointOnAxis_X,pointOnAxis_Z:圆锥中轴线上的任意一个点的X,Z坐标
    -- @param angle:圆锥的张角（角度制）
    -- @return:外切圆的圆心坐标和半径

    -- 将角度转换为弧度
    local angleRad = math.rad(angle)

    -- 计算外切圆的半径
    local radius = maxRange / (1 + math.sin(angleRad / 2))

    -- 计算圆心到锥顶的距离
    local distanceToCenter = radius * math.sin(angleRad / 2)

    -- 计算中轴线的方向向量
    local directionX = pointOnAxis_X - centerX
    local directionZ = pointOnAxis_Z - centerZ
    local directionLength = math.sqrt(directionX * directionX + directionZ * directionZ)

    -- 归一化方向向量
    local normalizedDirectionX = directionX / directionLength
    local normalizedDirectionZ = directionZ / directionLength

    -- 计算外切圆圆心的坐标
    local excircleCenterX = centerX + normalizedDirectionX * distanceToCenter
    local excircleCenterZ = centerZ + normalizedDirectionZ * distanceToCenter

    -- 返回外切圆的圆心坐标和半径
    return {x = excircleCenterX, z = excircleCenterZ, r = radius}
end
-- 2/2 计算某个点有没有落在圆锥内
function tools:isEnemyInCone(checkX, checkZ, centerX, centerZ, pointOnAxis_X, pointOnAxis_Z, coneAngle, maxRange)
    -- @param: checkX, checkZ:要检查的点的坐标
    -- @param: centerX, centerZ:圆锥的圆心坐标
    -- @param: pointOnAxis_X, pointOnAxis_Z:圆锥中轴线上任意一个点的坐标
    -- @param: coneAngle:圆锥的张角（角度制）
    -- @param: maxRange:圆锥的最大长度

    -- 将角度转换为弧度
    local angleRad = math.rad(coneAngle)

    -- 计算圆锥的朝向向量
    local directionX = pointOnAxis_X - centerX
    local directionZ = pointOnAxis_Z - centerZ

    -- 计算检查点到圆锥圆心的向量
    local checkVectorX = checkX - centerX
    local checkVectorZ = checkZ - centerZ

    -- 计算两个向量之间的点积
    local dotProduct = directionX * checkVectorX + directionZ * checkVectorZ

    -- 计算两个向量的模长
    local directionMagnitude = math.sqrt(directionX * directionX + directionZ * directionZ)
    local checkVectorMagnitude = math.sqrt(checkVectorX * checkVectorX + checkVectorZ * checkVectorZ)

    -- 防止除以零错误
    if directionMagnitude == 0 or checkVectorMagnitude == 0 then
        return false
    end

    -- 计算两个向量之间的夹角
    local angle = math.acos(dotProduct / (directionMagnitude * checkVectorMagnitude))

    -- 检查角度是否在圆锥张角之内
    if angle > angleRad / 2 then
        return false
    end

    -- 检查点到圆心的距离是否小于最大射程
    local distance = math.sqrt(checkVectorX * checkVectorX + checkVectorZ * checkVectorZ)
    if distance > maxRange then
        return false
    end

    return true
end
-- 找距离最近的怪
function tools:findClosestMobToPoint(x,y,z,radius)
    local ents = TheSim:FindEntities(x, y, z, radius, {'locomotor'},{'INLIMBO','player','companion','wall'})
    local radius_fixed = radius^2
    local closest = nil
    for _,v in pairs(ents or {}) do
        if v and v:IsValid() and v.components and v.components.combat and v.components.health and not v.components.health:IsDead() then
            local v_x,_,v_z = v.Transform:GetWorldPosition()
            local dist =  self:calcDist(v_x,v_z,x,z)
            if dist < radius_fixed then
                closest = v
                radius_fixed = dist
            end
        end
    end
    return closest
end

return tools 